#pragma once

// 引入所需的头文件
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <mutex>
#include <unordered_map>
#include <boost/algorithm/string.hpp>
#include "log.hpp" 
#include "cppjieba/include/cppjieba/Jieba.hpp" // 引入cppjieba库

// 定义命名空间ns_util
namespace ns_util {
    // 文件工具类，提供读取文件内容的功能
    class FileUtil {
    public:
        // 静态函数，用于读取文件内容到字符串
        static bool ReadFile(const std::string &file_path, std::string *out) {
            // 使用ifstream打开文件
            std::ifstream in(file_path, std::ios::in);
            if (!in.is_open()) {
                // 如果文件打开失败，输出错误信息并返回false
                LOG(ERROR, "open file" + file_path + " error");
                return false;
            }

            // 逐行读取文件内容并追加到out参数指向的字符串中
            std::string line;
            while (std::getline(in, line)) {
                *out += line;
            }

            // 关闭文件并返回true
            in.close();
            return true;
        }
    };

    // 字符串工具类，提供字符串分割的功能
    class StringUtil {
    public:
        // 静态函数，用于分割字符串
        static void Split(const std::string &target, std::vector<std::string> *out, const std::string &sep) {
            // 使用boost库的split函数进行字符串分割
            boost::split(*out, target, boost::is_any_of(sep), boost::token_compress_on);
        }
    };

    // 定义一些字典路径常量
    const char* const DICT_PATH = "./dict/jieba.dict.utf8";
    const char* const HMM_PATH = "./dict/hmm_model.utf8";
    const char* const USER_DICT_PATH = "./dict/user.dict.utf8";
    const char* const IDF_PATH = "./dict/idf.utf8";
    const char* const STOP_WORD_PATH = "./dict/stop_words.utf8";

    // 定义中文分词工具类JiebaUtil
    class JiebaUtil {
    private:
        // cppjieba分词器实例
        cppjieba::Jieba jieba;
        // 停用词哈希表
        std::unordered_map<std::string, bool> stop_words;

    private:
        // 构造函数，初始化cppjieba分词器
        JiebaUtil() : jieba(DICT_PATH, HMM_PATH, USER_DICT_PATH, IDF_PATH, STOP_WORD_PATH) {}
        // 禁止拷贝构造函数
        JiebaUtil(const JiebaUtil&) = delete;

        // 单例模式的实例指针
        static JiebaUtil *instance;
    public:
        // 单例模式获取实例的方法
        static JiebaUtil* get_instance() {
            static std::mutex mtx;
            if (nullptr == instance) {
                mtx.lock();
                if (nullptr == instance) {
                    instance = new JiebaUtil();
                    instance->InitJiebaUtil();
                }
                mtx.unlock();
            }
            return instance;
        }

        // 初始化方法，加载停用词
        void InitJiebaUtil() {
            std::ifstream in(STOP_WORD_PATH);
            if (!in.is_open()) {
                // 如果停用词文件打开失败，记录日志并返回
                LOG(FATAL, "load stop words file error");
                return;
            }

            // 读取停用词文件并添加到哈希表中
            std::string line;
            while (std::getline(in, line)) {
                stop_words.insert({line, true});
            }

            // 关闭文件
            in.close();
        }

        // 辅助函数，用于分词并过滤停用词
        void CutStringHelper(const std::string &src, std::vector<std::string> *out) {
            // 使用cppjieba分词器进行分词
            jieba.CutForSearch(src, *out);
            // 遍历分词结果，移除停用词
            for (auto iter = out->begin(); iter != out->end(); ) {
                auto it = stop_words.find(*iter);
                if (it != stop_words.end()) {
                    // 如果当前词是停用词，erase移除并更新迭代器
                    iter = out->erase(iter);
                } else {
                    // 否则，移动到下一个词
                    ++iter;
                }
            }
        }

        // 静态函数，提供分词服务
        static void CutString(const std::string &src, std::vector<std::string> *out) {
            // 调用实例的辅助函数进行分词
            ns_util::JiebaUtil::get_instance()->CutStringHelper(src, out);
        }
    };

    // 初始化单例模式的实例指针
    JiebaUtil *JiebaUtil::instance = nullptr;
}